﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
using Perspective.Wpf3D.Shapes;
using System.Windows.Media.Animation;
using System.Threading;
using WPFMediaKit.DirectShow.Controls;

namespace Wpf3dCollaborative
{
    /// <summary>
    /// Logique d'interaction pour Webcam.xaml
    /// </summary>
    public partial class Cam : Square3D, IDisposable
    {

        // Gestion de la position/échelle de l' object :
        public Transformer3D Transforms = new Transformer3D();

        private Object Player;
        private bool disposed = false;

        /// <summary>
        /// Type de média ( Vidéo, webcam, caméra IP...)
        ///  </summary>
        public enum TypeCam
        {
            /// <summary>
            /// Caméra planté
            /// </summary>
            ERR,

            /// <summary>
            /// Webcam standard
            /// </summary>
            WEBCAM,

            /// <summary>
            /// Caméra Ip ( Rtp, Rtsp, Rtpm, UDP)
            /// </summary>
            IPCAM,

            /// <summary>
            /// Fichiers vidéos (tout type de codec géré selon vos codecs système)
            /// </summary>            
            VIDEO,

            /// <summary>
            /// Caméra non configuré ( Image )
            /// </summary>
            UNCONFIGURED
        };

        private int CurrentAngle = 0;

        /// <summary>
        /// Url Absolue de la source exemple "axrtsp://192.168.0.90:554/mpeg4/media.amp"
        /// </summary>
        public string Source = "ASUS USB2.0 WebCam";
        // public string Source = "axrtsp://192.168.0.90:554/mpeg4/media.amp";

        public bool IsPlaying = false;
        public Boolean IsWideCam = false;
        public bool IsFullScreen = false;



        private string _Id;
        public string Id
        {
            get { return _Id; }
            set { _Id = value; }
        }


        private TypeCam _TypeCamera;


        /// <summary>
        /// Permet de choisir le Type de caméra : Attention la caméra s'initialise automatiquement  avec la source précédente
        /// </summary>
        public TypeCam TypeCamera
        {
            get { return _TypeCamera; }

            set
            {
                _TypeCamera = value;
                Update(); // On met à jour la caméra
            }
        }



        public Cam()
        {
            InitializeComponent();

            Transform = Transforms.GlobalTransform;

        }

        #region player
        public void Play()
        {
            if (Player is MediaUriElement)
            {
                ((MediaUriElement)Player).Play();
                IsPlaying = true;
            }
            else
            {
                if (Player is VideoCaptureElement)
                {
                    ((VideoCaptureElement)Player).Play();
                    IsPlaying = true;
                }

                if (Player is MediaElement)
                {
                    ((MediaElement)Player).Play();
                    IsPlaying = true;
                }
            }


        }

        public void Stop()
        {
            if (Player is MediaUriElement)
            {
                ((MediaUriElement)Player).Stop();
      
                IsPlaying = false;
            }
            else
            {
                if (Player is VideoCaptureElement)
                {
                    ((VideoCaptureElement)Player).Stop();
              
                    IsPlaying = false;
                }

                if (Player is MediaElement)
                {

                    ((MediaElement)Player).UnloadedBehavior = MediaState.Manual;
                    ((MediaElement)Player).Stop();
              

                    IsPlaying = false;
                }
            }


        }

        public void CleanPlayer()
        {
            if (Player is MediaUriElement)
            {
                ((MediaUriElement)Player).Stop();
                ((MediaUriElement)Player).Close();

                ((MediaUriElement)Player).MediaFailed -= MyMediaFailled;
                ((MediaUriElement)Player).Unloaded -= MyMediaFailled;
                IsPlaying = false;
            }
            else
            {
                if (Player is VideoCaptureElement)
                {
                    ((VideoCaptureElement)Player).Stop();
                    ((VideoCaptureElement)Player).Close();

                    ((VideoCaptureElement)Player).MediaFailed -= MyMediaFailled;
                    ((VideoCaptureElement)Player).Unloaded -= MyMediaFailled;
                    IsPlaying = false;
                }

                if (Player is MediaElement)
                {

                    ((MediaElement)Player).UnloadedBehavior = MediaState.Manual;
                    ((MediaElement)Player).Stop();
                    ((MediaElement)Player).Close();

                    ((MediaElement)Player).MediaFailed -= MyMediaFailled;
                    ((MediaElement)Player).Unloaded -= MyMediaFailled;
                    IsPlaying = false;
                }
            }


        }

        public void Pause()
        {

            if (Player is MediaUriElement)
            {
                ((MediaUriElement)Player).Stop();
                IsPlaying = false;
            }
            else
            {
                if (Player is VideoCaptureElement)
                {
                    ((VideoCaptureElement)Player).Stop();
                    IsPlaying = false;
                }

                if (Player is MediaElement)
                {
                    ((MediaElement)Player).UnloadedBehavior = MediaState.Manual;
                    ((MediaElement)Player).Pause();
                    IsPlaying = false;
                }
            }

        }

        public void SetResolution(int width, int height)
        {
            // videoCapElement.DesiredPixelWidth = width;
            //  videoCapElement.DesiredPixelHeight = height;
        }

        public void SetVolume(double volume)
        {
            try
            {
                switch (TypeCamera)
                {
                    case TypeCam.WEBCAM:
                        ((VideoCaptureElement)Player).Volume = volume;
                        ; break;

                    case TypeCam.IPCAM:
                        ((MediaUriElement)Player).Volume = volume;
                        ; break;

                    case TypeCam.VIDEO:
                        ((MediaUriElement)Player).Volume = volume;
                        ; break;

                }
            }
            catch (Exception Ex)
            {
                Console.WriteLine("[Ex Audio Volume Normale]:" + Ex.StackTrace);
            }

        }

        public double GetVolume() 
        {
            try
            {
                switch (TypeCamera)
                {
                    case TypeCam.WEBCAM:
                        return ((VideoCaptureElement)Player).Volume;
                        ; break;

                    case TypeCam.IPCAM:
                        return ((MediaUriElement)Player).Volume;
                        ; break;

                    case TypeCam.VIDEO:
                        return ((MediaElement)Player).Volume;
                        ; break;

                }

            }
            catch (Exception Ex)
            {
                Console.WriteLine("[Ex Audio Volume Normale]:" + Ex.StackTrace);
            }
            return 0;
        }
        #endregion player


        public void SetWideScreenCam()
        {
          Console.WriteLine(IsWideCam);
          Transforms.SetWideScreen(ref  IsWideCam);
          Console.WriteLine(IsWideCam);
        }



        public void Inverser()
        {
            DoubleAnimation AnimInverse = new DoubleAnimation();
            AnimInverse.From = CurrentAngle;

            if (CurrentAngle == 180)
            {
                AnimInverse.To = 0;
                CurrentAngle = 0;
            }
            else
            {
                AnimInverse.To = 180;
                CurrentAngle = 180;
            }

            AnimInverse.Duration = new Duration(TimeSpan.FromMilliseconds(400));

            Rotatecam.BeginAnimation(RotateTransform.AngleProperty,
AnimInverse);


        }



        /* Fonction de gestion du type camera */

        public void Update()
        {
            Content.Visual = null;
            Stop();
            CleanPlayer();
            Player = null;

            switch (TypeCamera)
            {
                case TypeCam.WEBCAM:

                    Player = new VideoCaptureElement();

                    ((VideoCaptureElement)Player).LoadedBehavior = WPFMediaKit.DirectShow.MediaPlayers.MediaState.Manual;
                    ((VideoCaptureElement)Player).FPS = 25;
                    ((VideoCaptureElement)Player).Stretch = Stretch.Fill;
                    IsPlaying = true;


                    Content.Visual = (VideoCaptureElement)Player;
                    ((VideoCaptureElement)Player).VideoCaptureSource = Source; //"ASUS USB2.0 WebCam";

                    ((VideoCaptureElement)Player).Play();

                    ; break;

                case TypeCam.IPCAM:

                    Player = new MediaUriElement();

                    ((MediaUriElement)Player).MediaFailed += MyMediaFailled;
                    ((MediaUriElement)Player).Unloaded += MyMediaFailled;

                    ((MediaUriElement)Player).LoadedBehavior = WPFMediaKit.DirectShow.MediaPlayers.MediaState.Manual;

                    Content.Visual = (MediaUriElement)Player;
                    try
                    {
                        ((MediaUriElement)Player).Source = new Uri(Source, UriKind.RelativeOrAbsolute);
                        ((MediaUriElement)Player).VideoRenderer = WPFMediaKit.DirectShow.MediaPlayers.VideoRendererType.EnhancedVideoRenderer;
                        Console.WriteLine(Source);
                        Play();
                    }
                    catch (UriFormatException ex)
                    {
                        MessageBox.Show("Url mal formée");
                    }


                    ; break;

                case TypeCam.VIDEO:

                    Player = new MediaUriElement();
                    ((MediaUriElement)Player).Volume = 0;
                    ((MediaUriElement)Player).MediaFailed += MyMediaFailled;
                    ((MediaUriElement)Player).Unloaded += MyMediaFailled;
                    ((MediaUriElement)Player).VideoRenderer = WPFMediaKit.DirectShow.MediaPlayers.VideoRendererType.EnhancedVideoRenderer;
                    ((MediaUriElement)Player).LoadedBehavior = WPFMediaKit.DirectShow.MediaPlayers.MediaState.Manual;
                    ((MediaUriElement)Player).UnloadedBehavior = WPFMediaKit.DirectShow.MediaPlayers.MediaState.Manual;

                    IsPlaying = true;

                    Content.Visual = (MediaUriElement)Player;
                    ((MediaUriElement)Player).Source = new Uri(Source, UriKind.RelativeOrAbsolute);
                    //  ((MediaUriElement)Player).Source = new Uri("D:/Users/dfi/Desktop/shakira.mkv", UriKind.RelativeOrAbsolute);

                    Play();

                    ; break;

                case TypeCam.UNCONFIGURED:

                    Player = new Image();
                    string uriSource = "pack://application:,,,/wpf3dCollaborative;component/Images/configuration.png";
                    ((Image)Player).Source = new ImageSourceConverter().ConvertFromString(uriSource) as ImageSource;
                    Content.Visual = (Image)Player;
                    ; break;

            }

        }



        /* Met a jours la position et la rotation pour le caroussel */



        public void AfficherOptionCam(Point p, MenuCam m)
        {


            // On affiche le menu de gestion de la caméra
            m.CameraName.Text = Id;
            Thickness a = new Thickness(p.X, p.Y, 0, 0);
            m.Margin = a;
            m.SetOwnerCam(this);
            if (!IsPlaying)
            {
                m.BtnPlay.Content = "►";
            }
            else
            {
                m.BtnPlay.Content = "||";
            }

            if (!IsWideCam)
            {
                m.Mode16.IsChecked = false;
            }
            else
            {
                m.Mode16.IsChecked = true;
            }


            /* TODO Configuration du menu selon le type de cam */
            switch (TypeCamera)
            {
                case TypeCam.ERR: ; break;
                case TypeCam.UNCONFIGURED:
                    App.windows.Menu.videoCapDevices.SelectedIndex = 0;
                    App.windows.Menu.checkWebcam.IsChecked = true; break;
                case TypeCam.IPCAM:

                    App.windows.Menu.checkcam.IsChecked = true;
                    App.windows.Menu.campIp.Text = Source;
                    App.windows.Menu.sliderVolume.Value = GetVolume();
                    ; break;
                case TypeCam.WEBCAM:
                    App.windows.Menu.checkWebcam.IsChecked = true;
                    App.windows.Menu.sliderVolume.Value = GetVolume();
                    ; break;
                case TypeCam.VIDEO:
                    App.windows.Menu.videoCapDevices.SelectedIndex = 0;
                    App.windows.Menu.sliderVolume.Value = GetVolume();
                    App.windows.Menu.checkVideo.IsChecked = true;
                    App.windows.Menu.campIp.Text = Source;

                    ; break;

            }


            App.windows.Menu.Visibility = Visibility.Visible;
            App.windows.Menu.Visibility = Visibility.Visible;

        }



        #region Destructor
        private void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                //Nettoyage des ressources
                if (disposing)
                {

                    Console.WriteLine("[DESTRUCTION CAM]" + Id);
                    this.Dispatcher.Invoke(
                       System.Windows.Threading.DispatcherPriority.Normal,
                       new Action(
                         delegate()
                         {
                             CleanPlayer();
                             Content.Visual = null;

                         }));


                    // On détache les événements
                    MouseLeftButtonUp -= Square3D_MouseLeftButtonUp;
                    MouseMove -= Square3D_MouseMove;

                    MouseRightButtonUp -= Square3D_MouseRightButtonDown;
                    MouseLeftButtonDown -= Square3D_MouseLeftButtonDown;
                    LostMouseCapture -= Square3D_LostMouseCapture;
                    PreviewTextInput -= Square3D_PreviewTextInput;

                    MouseWheel -= Square3D_MouseWheel;
                    

                    Player = null;

                    App.windows.Menu.CurrentCam = null;

                    Transforms.Dispose();
                }


            }
            disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);

            GC.SuppressFinalize(this);
        }

        ~Cam()
        {

            Dispose(false);
        }
        #endregion Destructor


    }
}
